package AQS;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;

/**
 * @author: 李德才
 * @description:
 * @create: 2020-12-13 14:48
 **/
public class TestVarHandle {
    int x = 8;
    public String string = "hello";
    Integer i = 1;

    private static VarHandle intHandle;
    private static VarHandle integerHandle;
    private static VarHandle strHandle;
    private static TestVarHandle t = new TestVarHandle();

    static {
        try {
            /**
             * MethodHandles.privateLookupIn(class, MethodHandles.lookup())获取访问私有变量的 Lookup
             * MethodHandles.lookup() 获取访问 protected、public 的 Lookup
             *
             * findVarHandle：用于创建对象中非静态字段的VarHandle。接收参数有三个，第一个为接收者的 class 对象，第二个是字段名称，第三个是字段类型。
             * findStaticVarHandle：用于创建对象中静态字段的VarHandle，接收参数与findVarHandle一致。
             *
             * unreflectVarHandle：通过反射字段Field创建VarHandle。
             * MethodHandles.arrayElementVarHandle(int[].class)  获取管理数组的 Varhandle
             */
            intHandle = MethodHandles.lookup().findVarHandle(TestVarHandle.class, "x", int.class);
            integerHandle = MethodHandles.lookup().findVarHandle(TestVarHandle.class, "i", Integer.class);
            strHandle = MethodHandles.lookup().findVarHandle(TestVarHandle.class, "string", String.class);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }


    /**
     * 基于 VarHandle 实现 int 类型的CAS
     */
    public static void testCompareAndSetForInt() {
        System.out.println((int) intHandle.get(t)); // 8
        intHandle.set(t, 9);  // 9
        System.out.println(t.x);
        /**
         * 可以保证原子性
         * 自旋锁：每次更新都会比对预期值是否相等，如果相等则更新，不相等则不更新
         */
        intHandle.compareAndSet(t, 9, 10);  //  预期值 9 ,设置为 10
        System.out.println(t.x);
        intHandle.getAndAdd(t, 10);  // 自增 10 具有原子性
        System.out.println(t.x);
    }

    /**
     * 基于 VarHandle 实现 Integer 类型的CAS
     * 但是注意这里比较的是内存地址，注意Integer 自动拆装箱问题
     */
    public void testCompareAndSetForInteger() {
        integerHandle.set(t, 1);
        integerHandle.compareAndSet(t, 1, 2);
        System.err.println(integerHandle.compareAndSet(t, 2, 301));
        System.err.println(integerHandle.compareAndSet(t, 301, 300));
    }


    /**
     * 基于 VarHandle 实现 String 类型的CAS
     * 字符串更要注意地址问题
     */
    public static void testCompareAndSetForString() {
        System.err.println(strHandle.get(t));
        System.err.println(strHandle.compareAndSet(t, t.string, "hello2"));
        System.err.println(strHandle.compareAndSet(t, new String("hello"), "hello2"));
    }


    /**
     * AtomicInteger，一个提供原子操作的Integer的类。在Java语言中，++i和i++操作并不是线程安全的，
     * 在使用的时候，不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口
     */
    public void atomicInteger() {
        AtomicInteger atomicInteger = new AtomicInteger(1);
        boolean flag = atomicInteger.compareAndSet(1, 2);
        System.err.println(flag);
        flag = atomicInteger.compareAndSet(5, 6);
        System.err.println(flag);
    }

    /**
     * AtomicIntegerArray，一个提供原子操作的Integer数组的类。
     */
    public void atomicIntegerArray() {
        AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(3);
        atomicIntegerArray.set(0, 1);
        System.err.println("atomicIntegerArray===>" + atomicIntegerArray.compareAndSet(0, 1, 2));
        System.err.println("atomicIntegerArray===>" + atomicIntegerArray.compareAndSet(0, 3, 4));
    }


    public static void main(String[] args) {
//        testCompareAndSetForInt();
        testCompareAndSetForString();
    }

}
